package com.webframe.util;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.webframe.service.def.IMenuService;
import com.webframe.service.impl.MenuService;

public class MenuUtil
{

	public static MenuUtil		theInstance;

	private final String			RootPID	= "-1";

	private MenuItem				menu;

	private IMenuService			menuService;

	private static final Log	log		= LogFactory.getLog(MenuUtil.class);

	public MenuUtil()
	{
		menu = null;
	}
	
	/**
	 * 设置Menu
	 * 
	 * @function:
	 * @param null (auto Set the rootId = -1)
	 * @return MenuItem
	 * @throws Exception
	 **/
	public MenuItem getMenu() throws Exception
	{
		/*返回实例,需要重启<项目完成后可以开启>
		 *  if(menu == null){
			 menu = initMenu(RootPID);
		 }
		 * */
		menu = initMenu(RootPID);
		return menu;
	}

	/**
	 * 设置Menu
	 * 
	 * @function:
	 * @param String rootId(自定义根节点)
	 * @return MenuItem
	 * @throws Exception
	 **/
	public MenuItem getMenu(String rootId) throws Exception
	{
		/*返回实例,需要重启<项目完成后可以开启>
		 *  if(menu == null){
			 menu = initMenu(RootPID);
		 }
		 * */
		menu = initMenu(rootId);
		return menu;
	}

	/**
	 * 设置Menu
	 * 
	 * @function:
	 * @param Boolean (True:set the Menu from the xml;False:auto call the getMenu() function)
	 * @param String (the name of XmlFile)
	 * @return MenuItem
	 * @throws Exception
	 **/
	public MenuItem getMenu(Boolean useXML, String xmlName) throws Exception
	{
		/*返回实例,需要重启<项目完成后可以开启>
		 *  if(menu == null){
			 menu = initMenu(RootPID);
		 }
		 * */
		menu = initMenu(useXML, xmlName);
		return menu;
	}

	/**
	 * 获得所有的首页
	 * 
	 * @function:
	 * @param String rootId(自定义根节点)
	 * @return MenuItem(用于自定义根节点返回所有的首页)
	 * @throws Exception
	 **/
	public MenuItem[] getIndexPages(String rootId) throws Exception
	{
		/*返回实例,需要重启<项目完成后可以开启>
		 *  if(menu == null){
			 menu = initMenu(RootPID);
		 }
		 * */
		menu = initMenu(rootId);
		return menu.getSubMenus();
	}

	public MenuItem initMenu(String pID) throws Exception
	{
		MenuItem menuItem = new MenuItem();
		menuItem.setSubMenus(getSubMenus(pID));
		return menuItem;
	}

	public MenuItem initMenu(Boolean useXML, String xmlName) throws Exception
	{
		if (false == useXML)
		{
			getMenu();
		}
		MenuItem menuItem = new MenuItem();
		menuItem.setSubMenus(getSubMenusFromXMLFile("/" + xmlName));
		return menuItem;
	}

	@SuppressWarnings("rawtypes")
	public MenuItem[] getSubMenus(String pID) throws Exception
	{
		MenuItem subMenus[] = null;
		menuService = (IMenuService) ToolSpring.getBean("menuService");
		List menuList = menuService.GetMenusByPID(pID);
		if (!menuList.isEmpty())
		{
			subMenus = new MenuItem[menuList.size()];
			for (int i = 0; i < menuList.size(); i++)
			{
				MenuItem menuItem = new MenuItem();
				Map menu = (Map) menuList.get(i);
				String menuID = menu.get("ID_").toString();
				menuItem.setName((String) menu.get("NAME_"));
				menuItem.setUrl((String) menu.get("URL_"));
				menuItem.setServletParams((String) menu.get("PARAM_"));
				menuItem.setPic((String) menu.get("PIC_"));
				menuItem.setRoles(getRolesByMenuID(menuID));
				menuItem.setSubMenus(getSubMenus(menuID));
				subMenus[i] = menuItem;
			}
		}
		else
		{
			subMenus = new MenuItem[]{};
		}
		return subMenus;
	}

	public MenuItem[] getSubMenusFromXMLFile(String XMLFilePath) throws Exception
	{
		MenuItem[] subMenus = null;
		MenuItem xmlMenu;
		try
		{
			java.io.InputStream menuXMl = getClass().getResourceAsStream(XMLFilePath);
			DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
			Document menuDoc = domBuilder.parse(menuXMl);
			xmlMenu = parseMenuItem(menuDoc.getDocumentElement());
			if (null != xmlMenu && null != xmlMenu.getSubMenus()) subMenus = xmlMenu.getSubMenus();
		} catch (Exception e)
		{
			log.error(e);
			throw e;
		}
		return subMenus;
	}

	@SuppressWarnings({
				"rawtypes", "unchecked"})
	protected MenuItem parseMenuItem(Element itemNode)
	{
		MenuItem menuItem = new MenuItem();
		menuItem.setName(itemNode.getAttribute("name"));
		if (itemNode.hasAttribute("url")) menuItem.setUrl(itemNode.getAttribute("url"));
		if (itemNode.hasAttribute("servletParams")) menuItem.setServletParams(itemNode.getAttribute("servletParams"));
		List subMenus = new ArrayList();
		List roles = new ArrayList();
		if (itemNode.hasChildNodes())
		{
			for (int i = 0; i < itemNode.getChildNodes().getLength(); i++)
			{
				Node child = itemNode.getChildNodes().item(i);
				if ("sub-items".equals(child.getNodeName()))
				{
					for (int j = 0; j < child.getChildNodes().getLength(); j++)
					{
						Node menuChild = child.getChildNodes().item(j);
						if ("menu-item".equals(menuChild.getNodeName())) subMenus.add(parseMenuItem((Element) menuChild));
					}
				}
				if ("roles".equals(child.getNodeName()))
				{
					for (int k = 0; k < child.getChildNodes().getLength(); k++)
					{
						Node roleChild = child.getChildNodes().item(k);
						if ("role".equals(roleChild.getNodeName()))
						{
							roles.add(roleChild.getFirstChild().getNodeValue());
						}
					}
				}
			}
		}
		menuItem.setSubMenus((MenuItem[]) (MenuItem[]) subMenus.toArray(new MenuItem[subMenus.size()]));
		menuItem.setRoles((String[]) roles.toArray(new String[roles.size()]));
		return menuItem;
	}

	@SuppressWarnings("rawtypes")
	public String[] getRolesByMenuID(String menuID) throws Exception
	{
		List roleList = menuService.getRolesByMenuID(menuID);
		String[] roles = null;
		if (roleList != null && roleList.size() > 0)
		{
			roles = new String[roleList.size()];
		}
		for (int i = 0; i < roleList.size(); i++)
		{
			String roleName = ((Map) roleList.get(i)).get("ROLE_").toString();
			roles[i] = roleName;
		}
		return roles;
	}

	public static MenuUtil instance()
	{
		if (theInstance == null)
		{
			theInstance = new MenuUtil();
		}
		return theInstance;
	}

	public class MenuItem
	{

		private String	name;

		private String	url;

		private String	servletParams;

		private String	pic;

		private MenuItem[] subMenus;
		
		private String[] roles;
		
		private boolean hasSubMenus;
		
		private boolean hasIcon;
		
		private String rolesStr;
		
		public String getPic()
		{
			return pic;
		}

		public void setPic(String pic)
		{
			this.pic = pic;
		}

		public String getName()
		{
			return this.name;
		}

		public void setName(String name)
		{
			this.name = name;
		}
		
		public String getUrl()
		{
			return url;
		}

		public void setUrl(String url)
		{
			this.url = url;
		}
		
		public String getServletParams()
		{
			return servletParams;
		}

		public void setServletParams(String servletParams)
		{
			this.servletParams = servletParams;
		}
		
		public MenuItem[] getSubMenus()
		{
			return subMenus;
		}

		public void setSubMenus(MenuItem[] subMenus)
		{
			this.subMenus = subMenus;
		}
		
		public String[] getRoles()
		{
			return roles;
		}

		public void setRoles(String[] roles)
		{
			this.roles = roles;
		}
		
		// 判断是否有子菜单
		public boolean getHasSubMenus()
		{
			this.hasSubMenus = subMenus != null && subMenus.length > 0;
			return this.hasSubMenus;
		}

		// 判断是否具有图标
		public Boolean getHasIcon()
		{
			this.hasIcon = StringUtils.isNotEmpty(this.url);
			return this.hasIcon;
		}

		// 是否具有权限
		public String getRolesStr()
		{
			StringBuffer sb = new StringBuffer();
			if (roles != null && roles.length > 0)
			{
				for (int i = 0; i < roles.length; i++)
				{
					sb.append(roles[i]);
					if (i < roles.length - 1)
					{
						sb.append(",");
					}
				}
			}
			this.rolesStr = sb.toString();
			return this.rolesStr;
		}
	}
}